From 75a6dedd5b533ef2d1b208140aaa24ccb3fe7f3f Mon Sep 17 00:00:00 2001 From: tsteven4 <13596209+tsteven4@users.noreply.github.com> Date: Thu, 13 Apr 2023 15:33:18 -0600 Subject: [PATCH] add support for dynamic filters (#1008) * support dynamic filters. * delete static ResampleFilter. * make some more filters dynamic. * parrot Vecs::find_vec in FilterVecs::find_filter_vec. --------- Co-authored-by: Robert Lipe --- filter_vecs.cc | 177 ++++++++++++++++++++++++++++++------------------- filter_vecs.h | 34 +++++++++- main.cc | 26 ++++++-- vecs.cc | 2 +- vecs.h | 2 +- 5 files changed, 164 insertions(+), 77 deletions(-) diff --git a/filter_vecs.cc b/filter_vecs.cc index 78a69a5d5..00308b71c 100644 --- a/filter_vecs.cc +++ b/filter_vecs.cc @@ -57,6 +57,12 @@ #include "validate.h" // for ValidateFilter #include "vecs.h" // for Vecs +template +Filter* fltfactory() +{ + static_assert(std::is_base_of::value, "T must be derived from Filter"); + return new T(); +} struct FilterVecs::Impl { ArcDistanceFilter arcdist; @@ -65,19 +71,14 @@ struct FilterVecs::Impl { DuplicateFilter duplicate; HeightFilter height; InterpolateFilter interpolate; - NukeDataFilter nukedata; PolygonFilter polygon; PositionFilter position; RadiusFilter radius; - ResampleFilter resample; ReverseRouteFilter reverse_route; SimplifyRouteFilter routesimple; - SortFilter sort; StackFilter stackfilt; SwapDataFilter swapdata; TrackFilter trackfilter; - TransformFilter transform; - ValidateFilter validate; const QVector filter_vec_list = { #if FILTERS_ENABLED @@ -107,9 +108,10 @@ struct FilterVecs::Impl { "Interpolate between trackpoints" }, { - &nukedata, + nullptr, "nuketypes", - "Remove all waypoints, tracks, or routes" + "Remove all waypoints, tracks, or routes", + &fltfactory }, { &polygon, @@ -127,9 +129,10 @@ struct FilterVecs::Impl { "Include Only Points Within Radius", }, { - &resample, + nullptr, "resample", "Resample Track", + &fltfactory }, { &routesimple, @@ -137,9 +140,10 @@ struct FilterVecs::Impl { "Simplify routes", }, { - &sort, + nullptr, "sort", "Rearrange waypoints, routes and/or tracks by resorting", + &fltfactory }, { &stackfilt, @@ -157,9 +161,10 @@ struct FilterVecs::Impl { "Manipulate track lists" }, { - &transform, + nullptr, "transform", - "Transform waypoints into a route, tracks into routes, ..." + "Transform waypoints into a route, tracks into routes, ...", + &fltfactory }, { &height, @@ -172,9 +177,10 @@ struct FilterVecs::Impl { "Swap latitude and longitude of all loaded points" }, { - &validate, + nullptr, "validate", - "Validate internal data structures" + "Validate internal data structures", + &fltfactory } #elif defined (MINIMAL_FILTERS) { @@ -193,63 +199,70 @@ FilterVecs& FilterVecs::Instance() return instance; } -Filter* FilterVecs::find_filter_vec(const QString& vecname) +void FilterVecs::prepare_filter(const fltinfo_t& fltdata) { - QStringList options = vecname.split(','); - if (options.isEmpty()) { - fatal("A filter name is required.\n"); - } - const QString svecname = options.takeFirst(); + QVector* args = fltdata->get_args(); - for (const auto& vec : d_ptr_->filter_vec_list) { - if (svecname.compare(vec.name, Qt::CaseInsensitive) != 0) { - continue; - } + Vecs::validate_options(fltdata.options, args, fltdata.fltname); - QVector* args = vec.vec->get_args(); - - Vecs::validate_options(options, args, vec.name); + /* step 1: initialize by inifile or default values */ + if (args && !args->isEmpty()) { + assert(args->isDetached()); + for (auto& arg : *args) { + QString qtemp = inifile_readstr(global_opts.inifile, fltdata.fltname, arg.argstring); + if (qtemp.isNull()) { + qtemp = inifile_readstr(global_opts.inifile, "Common filter settings", arg.argstring); + } + if (qtemp.isNull()) { + Vecs::assign_option(fltdata.fltname, &arg, arg.defaultvalue); + } else { + Vecs::assign_option(fltdata.fltname, &arg, qtemp); + } + } + } - /* step 1: initialize by inifile or default values */ + /* step 2: override settings with command-line values */ + if (!fltdata.options.isEmpty()) { if (args && !args->isEmpty()) { assert(args->isDetached()); for (auto& arg : *args) { - QString qtemp = inifile_readstr(global_opts.inifile, vec.name, arg.argstring); - if (qtemp.isNull()) { - qtemp = inifile_readstr(global_opts.inifile, "Common filter settings", arg.argstring); - } - if (qtemp.isNull()) { - Vecs::assign_option(vec.name, &arg, arg.defaultvalue); - } else { - Vecs::assign_option(vec.name, &arg, qtemp); + const QString opt = Vecs::get_option(fltdata.options, arg.argstring); + if (!opt.isNull()) { + Vecs::assign_option(fltdata.fltname, &arg, opt); } } } + } - /* step 2: override settings with command-line values */ - if (!options.isEmpty()) { - if (args && !args->isEmpty()) { - assert(args->isDetached()); - for (auto& arg : *args) { - const QString opt = Vecs::get_option(options, arg.argstring); - if (!opt.isNull()) { - Vecs::assign_option(vec.name, &arg, opt); - } - } - } - } + if (global_opts.debug_level >= 1) { + Vecs::disp_vec_options(fltdata.fltname, args); + } - if (global_opts.debug_level >= 1) { - Vecs::disp_vec_options(vec.name, args); - } +} + +FilterVecs::fltinfo_t FilterVecs::find_filter_vec(const QString& fltargstring) +{ + QStringList options = fltargstring.split(','); + if (options.isEmpty()) { + fatal("A filter name is required.\n"); + } + const QString fltname = options.takeFirst(); - return vec.vec; + for (const auto& vec : d_ptr_->filter_vec_list) { + if (fltname.compare(vec.name, Qt::CaseInsensitive) != 0) { + continue; + } + return {vec.vec, vec.name, options, vec.factory}; } - return nullptr; + + /* + * Not found. + */ + return {}; } -void FilterVecs::free_filter_vec(Filter* filter) +void FilterVecs::free_filter_vec(fltinfo_t& filter) { QVector* args = filter->get_args(); @@ -264,24 +277,30 @@ void FilterVecs::free_filter_vec(Filter* filter) } } +void FilterVecs::init_filter_vec(Filter* flt) +{ + QVector* args = flt->get_args(); + if (args && !args->isEmpty()) { + assert(args->isDetached()); + for (auto& arg : *args) { + arg.argvalptr = nullptr; + } + } +} + void FilterVecs::init_filter_vecs() { for (const auto& vec : d_ptr_->filter_vec_list) { - QVector* args = vec.vec->get_args(); - if (args && !args->isEmpty()) { - assert(args->isDetached()); - for (auto& arg : *args) { - arg.argvalptr = nullptr; - } + if (vec.vec != nullptr) { + init_filter_vec(vec.vec); } } } -void FilterVecs::exit_filter_vecs() +void FilterVecs::exit_filter_vec(Filter* flt) { - for (const auto& vec : d_ptr_->filter_vec_list) { - (vec.vec->exit)(); - QVector* args = vec.vec->get_args(); + (flt->exit)(); + QVector* args = flt->get_args(); if (args && !args->isEmpty()) { assert(args->isDetached()); for (auto& arg : *args) { @@ -291,6 +310,14 @@ void FilterVecs::exit_filter_vecs() } } } +} + +void FilterVecs::exit_filter_vecs() +{ + for (const auto& vec : d_ptr_->filter_vec_list) { + if (vec.vec != nullptr) { + exit_filter_vec(vec.vec); + } } } @@ -301,9 +328,10 @@ void FilterVecs::exit_filter_vecs() void FilterVecs::disp_filter_vecs() const { for (const auto& vec : d_ptr_->filter_vec_list) { + Filter* flt = (vec.factory != nullptr)? vec.factory() : vec.vec; printf(" %-20.20s %-50.50s\n", qPrintable(vec.name), qPrintable(vec.desc)); - const QVector* args = vec.vec->get_args(); + const QVector* args = flt->get_args(); if (args) { for (const auto& arg : *args) { if (!(arg.argtype & ARGTYPE_HIDDEN)) { @@ -313,6 +341,9 @@ void FilterVecs::disp_filter_vecs() const } } } + if (vec.factory != nullptr) { + delete flt; + } } } @@ -322,9 +353,10 @@ void FilterVecs::disp_filter_vec(const QString& vecname) const if (vecname.compare(vec.name, Qt::CaseInsensitive) != 0) { continue; } + Filter* flt = (vec.factory != nullptr)? vec.factory() : vec.vec; printf(" %-20.20s %-50.50s\n", qPrintable(vec.name), qPrintable(vec.desc)); - const QVector* args = vec.vec->get_args(); + const QVector* args = flt->get_args(); if (args) { for (const auto& arg : *args) { if (!(arg.argtype & ARGTYPE_HIDDEN)) { @@ -334,6 +366,9 @@ void FilterVecs::disp_filter_vec(const QString& vecname) const } } } + if (vec.factory != nullptr) { + delete flt; + } } } @@ -347,9 +382,10 @@ void FilterVecs::disp_help_url(const fl_vecs_t& vec, const arglist_t* arg) void FilterVecs::disp_v1(const fl_vecs_t& vec) { + Filter* flt = (vec.factory != nullptr)? vec.factory() : vec.vec; disp_help_url(vec, nullptr); printf("\n"); - const QVector* args = vec.vec->get_args(); + const QVector* args = flt->get_args(); if (args) { for (const auto& arg : *args) { if (!(arg.argtype & ARGTYPE_HIDDEN)) { @@ -366,6 +402,9 @@ void FilterVecs::disp_v1(const fl_vecs_t& vec) } } } + if (vec.factory != nullptr) { + delete flt; + } } /* @@ -402,7 +441,11 @@ void FilterVecs::disp_filters(int version) const bool FilterVecs::validate_filter_vec(const fl_vecs_t& vec) { - bool ok = Vecs::validate_args(vec.name, vec.vec->get_args()); + Filter* flt = (vec.factory != nullptr)? vec.factory() : vec.vec; + bool ok = Vecs::validate_args(vec.name, flt->get_args()); + if (vec.factory != nullptr) { + delete flt; + } return ok; } diff --git a/filter_vecs.h b/filter_vecs.h index 91b250b34..aa5323b66 100644 --- a/filter_vecs.h +++ b/filter_vecs.h @@ -31,6 +31,30 @@ class FilterVecs { // Meyers Singleton public: + + /* Types */ + + using FilterFactory = Filter* (*)(); + + class fltinfo_t { + public: + + bool isDynamic() { + return factory != nullptr; + } + explicit operator bool() const { + return ((flt != nullptr) || (factory != nullptr)); + } + Filter* operator->() const { + return flt; + } + + Filter* flt{nullptr}; + QString fltname; + QStringList options; + FilterFactory factory{nullptr}; + }; + /* Special Member Functions */ static FilterVecs& Instance(); @@ -41,9 +65,12 @@ public: /* Member Functions */ - Filter* find_filter_vec(const QString& vecname); - static void free_filter_vec(Filter* filter); + static void prepare_filter(const fltinfo_t& fltdata); + fltinfo_t find_filter_vec(const QString& fltargstring); + static void free_filter_vec(fltinfo_t& filter); + static void init_filter_vec(Filter* flt); void init_filter_vecs(); + static void exit_filter_vec(Filter* flt); void exit_filter_vecs(); void disp_filter_vecs() const; void disp_filter_vec(const QString& vecname) const; @@ -56,9 +83,10 @@ private: struct Impl; // Not defined here struct fl_vecs_t { - Filter* vec; + Filter* vec{nullptr}; QString name; QString desc; + FilterFactory factory{nullptr}; }; /* Special Member Functions */ diff --git a/main.cc b/main.cc index da928332e..d3a65301c 100644 --- a/main.cc +++ b/main.cc @@ -301,7 +301,7 @@ run(const char* prog_name) int argn; Vecs::fmtinfo_t ivecs; Vecs::fmtinfo_t ovecs; - Filter* filter = nullptr; + FilterVecs::fltinfo_t filter; QString fname; QString ofname; int opt_version = 0; @@ -451,10 +451,26 @@ run(const char* prog_name) filter = FilterVecs::Instance().find_filter_vec(argument); if (filter) { - filter->init(); - filter->process(); - filter->deinit(); - FilterVecs::free_filter_vec(filter); + if (filter.isDynamic()) { + filter.flt = filter.factory(); + FilterVecs::init_filter_vec(filter.flt); + FilterVecs::prepare_filter(filter); + + filter->init(); + filter->process(); + filter->deinit(); + FilterVecs::free_filter_vec(filter); + + FilterVecs::exit_filter_vec(filter.flt); + delete filter.flt; + filter.flt = nullptr; + } else { + FilterVecs::prepare_filter(filter); + filter->init(); + filter->process(); + filter->deinit(); + FilterVecs::free_filter_vec(filter); + } } else { fatal("Unknown filter '%s'\n",qPrintable(argument)); } diff --git a/vecs.cc b/vecs.cc index 1233a1b71..d4a6fb0d1 100644 --- a/vecs.cc +++ b/vecs.cc @@ -794,7 +794,7 @@ void Vecs::validate_options(const QStringList& options, const QVector } } -void Vecs::prepare_format(const fmtinfo_t& fmtdata) +void Vecs::prepare_format(const fmtinfo_t& fmtdata) { QVector* args = fmtdata->get_args(); diff --git a/vecs.h b/vecs.h index fcb15ee65..9c585d432 100644 --- a/vecs.h +++ b/vecs.h @@ -79,7 +79,7 @@ public: static void disp_vec_options(const QString& vecname, const QVector* args); static void validate_options(const QStringList& options, const QVector* args, const QString& name); static QString get_option(const QStringList& options, const QString& argname); - static void prepare_format(const fmtinfo_t& data) ; + static void prepare_format(const fmtinfo_t& data); fmtinfo_t find_vec(const QString& fmtargstring); void disp_vecs() const; void disp_vec(const QString& vecname) const; -- 2.30.2